package com.xjgz.aio.socket.enhance;

import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public final class FutureCompletionHandler<V, A> implements CompletionHandler<V, A>, Future<V> {
    // 异步处理结果
    private V result;

    // 异步操作是否完成
    private boolean done = false;

    // 异步操作是否被取消
    private boolean cancel = false;

    // 异步操作异常
    private Throwable exception;

    /**
     * 异步操作完成时调用
     */
    @Override
    public void completed(V result, A selectionKey) {
        this.result = result;
        this.done = true;
        synchronized (this) {
            this.notify();
        }
    }

    /**
     * 异步操作失败时调用
     */
    @Override
    public void failed(Throwable exc, A attachment) {
        this.exception = exc;
        this.done = true;
    }

    /**
     * 取消异步操作
     */
    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        if (done || cancel) return false;
        this.cancel = true;
        this.done = true;
        synchronized (this) {
            this.notify();
        }
        return true;
    }

    /**
     * 获取异步操作结果
     */
    @Override
    public synchronized V get() throws InterruptedException, ExecutionException {
        if (done) {
            if (exception != null) {
                throw new ExecutionException(exception);
            }
            return result;
        } else {
            this.wait();
        }
        return get();
    }

    /**
     * 获取异步操作结果，支持超时控制
     */
    @Override
    public synchronized V get(
        long timeout,
        TimeUnit unit
    ) throws InterruptedException, ExecutionException, TimeoutException {
        if (done) {
            return get();
        } else {
            this.wait(unit.toMillis(timeout));
        }
        if (done) {
            return get();
        }
        throw new TimeoutException();
    }

    /**
     * 判断异步操作是否被取消
     */
    @Override
    public boolean isCancelled() {
        return this.cancel;
    }

    /**
     * 判断异步操作是否完成
     */
    @Override
    public boolean isDone() {
        return this.done;
    }

}
